package main

import (
	"log"
	"os"

	"gopkg.in/macaron.v1"
)

// 服务覆盖映射

// type Logger interface {
// 	Println(interface{})
// }

// 全局服务第1步
var Logger = log.New(os.Stdout, "[APP] ", 0)

// 请求级别服务第1步
func myLogger(ctx *macaron.Context) {
	var logger = log.New(os.Stdout, "[myLogger] ", 0)
	ctx.Map(logger)
}

// 映射服务到接口 第1步
type LoggerInter interface {
	Println(...interface{})
}

// 定义一个映射服务到接口 第2步
func myLoggerInter(ctx *macaron.Context) {
	var logger = log.New(os.Stdout, "[MyLoggerInter] ", 0)
	ctx.MapTo(logger, (*LoggerInter)(nil)) // 将nil强制转换为接口类型
}

// 这里将logger变为不同的类型
type superLogger struct {
	*log.Logger // 匿名嵌入
}

// 服务的覆盖映射 第1步
func myLoggerInter2(ctx *macaron.Context) {
	var logger = log.New(os.Stdout, "[myLoggerOverMapping] ", 0)
	// 这里将logger变为不同的类型，得到和log.New得到不同的对象
	// 相同之处是，都拥有log.logger中的所有方法
	sl := &superLogger{logger}
	ctx.MapTo(sl, (*LoggerInter)(nil)) // sl和服务映射到接口中logger都一射到同一个接口LoggerInter
}

func main() {

	m := macaron.New()
	// 全局服务第2步
	m.Map(Logger)
	// 全局服务第3步
	m.Get("/", func(l *log.Logger) {
		l.Println("这是全局日志") // [APP] 这是全局日志
	})
	// 请求级别服务第2步
	m.Get("/123", myLogger, func(l *log.Logger) {
		l.Println("这是请求级别日志") // [myLogger] 这是请求级别日志
	})
	// 映射服务到接口 第3步，这里的Logger直接传入，不需要使用*
	m.Get("/123123", myLoggerInter, func(l LoggerInter) {
		l.Println("这是映射服务到接口日志") //[MyLoggerInter] 这是映射服务到接口日志
	})

	m.Get("/abc", myLoggerInter, myLoggerInter2, func(l LoggerInter) {
		// myLoggerInter2会覆盖myLoggerInter，这是服务的覆盖映射日志
		l.Println("这是服务的覆盖映射日志") //[myLoggerOverMapping] 这是服务的覆盖映射日志
	})

	m.Run()
}
